package com.lubase.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.lubase.core.entity.SsPageEntity;
import com.lubase.core.extend.IGetMainDataService;
import com.lubase.core.extend.PageDataExtendService;
import com.lubase.core.extend.service.InvokeMethodAdapter;
import com.lubase.core.model.DisplayListVO;
import com.lubase.core.model.QueryParamDTO;
import com.lubase.core.model.SearchCondition;
import com.lubase.core.service.*;
import com.lubase.core.util.ClientMacro;
import com.lubase.core.util.InvokeDataSourceService;
import com.lubase.core.util.SearchCondition2TableFilterService;
import com.lubase.model.DbField;
import com.lubase.model.DbTable;
import com.lubase.orm.QueryOption;
import com.lubase.orm.TableFilter;
import com.lubase.orm.constant.CommonConst;
import com.lubase.orm.exception.WarnCommonException;
import com.lubase.orm.model.DbCollection;
import com.lubase.orm.model.statistics.StatisticsOption;
import com.lubase.orm.operate.EOperateMode;
import com.lubase.orm.service.AppHolderService;
import com.lubase.orm.service.DataAccess;
import com.lubase.orm.service.query.StatisticsCoreService;
import com.lubase.orm.util.ServerMacroService;
import com.lubase.orm.util.TableFilterWrapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class RenderTableServiceImpl implements RenderTableService, RenderBaseService {

    @Autowired
    DataAccess dataAccess;

    @Autowired
    InvokeMethodAdapter invokeMethodAdapter;

    @Autowired
    SearchCondition2TableFilterService searchCondition2TableFilterService;

    @Autowired
    InvokeDataSourceService sqlDataSource;

    @Autowired
    ServerMacroService serverMacroService;

    @Autowired
    AppHolderService appHolderService;

    @Autowired
    PersonalizationDataService personalizationDataService;

    @Autowired
    StatisticsCoreService statisticsCoreService;
    @Autowired
    RenderTableExtendService gridDataExtendService;
    @Autowired
    RestTemplate restTemplate;
    @Autowired
    AppFuncDataService appFuncDataService;
    String urlTemplate;

    public RenderTableServiceImpl(Environment environment) {
        this.urlTemplate = String.format("%s/fulltext", environment.getProperty("lubase.fulltext-server"));
    }

    @Override
    public ServerMacroService getServerMacroService() {
        return serverMacroService;
    }

    @Override
    public DbCollection getGridDataByPageId(String pageId, ClientMacro clientMacro, String searchParamStr, String queryParamsStr, String fullTextSearch) {
        return getGridDataByPageId(pageId, clientMacro, searchParamStr, false, queryParamsStr, fullTextSearch);
    }

    @Override
    public DbCollection getGridAllDataByPageId(String pageId, ClientMacro clientMacro, String searchParamStr, String queryParamsStr, String fullTextSearch) {
        return getGridDataByPageId(pageId, clientMacro, searchParamStr, true, queryParamsStr, fullTextSearch);
    }

    private DbCollection getGridDataByPageId(String pageId, ClientMacro clientMacro, String searchParamStr, Boolean isAllData, String queryParamsStr, String fullTextSearch) {
        if (StringUtils.isEmpty(pageId)) {
            return null;
        }
        SsPageEntity pageEntity = appFuncDataService.getPageById(pageId);
        //todo:此处需要验证是否有页面权限
        if (pageEntity == null || StringUtils.isEmpty(pageEntity.getGrid_query())) {
            return null;
        }
        List<PageDataExtendService> extendServices = gridDataExtendService.getCurrentExtendService(pageId);
        QueryOption serverQuery = JSON.parseObject(pageEntity.getGrid_query(), QueryOption.class);
        if (isAllData) {
            serverQuery.setQueryMode(2);
        }
        QueryParamDTO clientQuery = JSON.parseObject(queryParamsStr, QueryParamDTO.class);

        DbCollection coll = null;
        if (serverQuery.getQueryType() == 2) {
            //注意: 只能接收无参数的方法。如果需要客户端传递的参数，请使用queryType=3。详见↓
            coll = sqlDataSource.queryDBCollectionBySql(Long.parseLong(pageId), serverQuery.getServerId());
        } else if (serverQuery.getQueryType() == 3) {
            IGetMainDataService service = invokeMethodAdapter.getMainDataService(serverQuery.getServerId());
            coll = service.exe(pageId, clientMacro);
        } else {
            //todo 这里是否适合*
            if (StringUtils.isEmpty(serverQuery.getFixField())) {
                serverQuery.setFixField("*");
            }
            if (StringUtils.isEmpty(fullTextSearch)) {
                replaceClientMacro(serverQuery.getTableFilter(), clientMacro);
                if (!StringUtils.isEmpty(searchParamStr)) {
                    List<SearchCondition> list = JSON.parseArray(searchParamStr, SearchCondition.class);
                    if(!ObjectUtils.isEmpty(list)) {
                        list.forEach(m->m.setColumnCode(m.getColumnCode().replace(CommonConst.REF_FIELD_SEPARATOR,".")));
                    }
                    TableFilter searchFilter = searchCondition2TableFilterService.convertToTableFilter(list);
                    if (searchFilter != null) {
                        if (serverQuery.getTableFilter().getChildFilters() == null) {
                            serverQuery.getTableFilter().setChildFilters(new ArrayList<>());
                        }
                        serverQuery.getTableFilter().getChildFilters().add(searchFilter);
                    }
                }
                mergeClientQuery(serverQuery, clientQuery);
            } else {
                //增加全文检索的支持
                String ids = "0";
                //从远端获取全文检索的id
                try {
                    String tmpIds = getIdListByFullTextSearch(pageId, fullTextSearch);
                    if (tmpIds != null) {
                        ids = tmpIds;
                    }
                } catch (Exception ex) {
                    log.error("全文检索查询失败,pageId" + pageId, ex);
                }
                if (clientQuery != null) {
                    //替换query中的查询参数
                    serverQuery.setPageIndex(clientQuery.getPageIndex());
                    serverQuery.setPageSize(clientQuery.getPageSize());
                }
                serverQuery.getTableFilter().getChildFilters().add(new TableFilter("id", ids, EOperateMode.In));
            }

            serverQuery.setEnableColAccessControl(true);
            gridDataExtendService.executePageTemplateExtend(pageEntity, serverQuery, clientMacro);
            gridDataExtendService.beforeExecuteQueryEvent(pageEntity, extendServices, serverQuery, clientMacro);
            coll = gridDataExtendService.executePageTemplate(pageEntity, serverQuery, clientMacro);
        }

        int i = 1;
        for (DbField f : coll.getTableInfo().getFieldList()) {
            f.setOrderId(i);
            i++;
        }
        //获取个性化配置。如果后续除了字段设定还增加别的设置信息，可设置VO对象，序列化后存储到此字段，共用 collection对象的personalization属性
        DisplayListVO displayListVO = personalizationDataService.getDisplaySetting(Long.parseLong(pageId), appHolderService.getUser().getId());
        String displayColumns = displayListVO.getColumnIds();
//        if (!StringUtils.isEmpty(displayColumns)) {
//            List<String> validList = new ArrayList<>();
//            List<DbField> allFieldList = coll.getTableInfo().getFieldList();
//            for (String columnId : displayColumns.split(",")) {
//                if (allFieldList.stream().anyMatch(d -> d.getId().equals(columnId))) {
//                    validList.add(columnId);
//                }
//            }
//            displayListVO.setColumnIds(String.join(",", validList));
//        }
        coll.setPersonalization(JSON.toJSONString(displayListVO));
        gridDataExtendService.beforeReturnPageTemplateExtend(pageEntity, coll, clientMacro);
        gridDataExtendService.beforeReturnMainDataEvent(pageId, extendServices, coll);
        return coll;
    }

    @Override
    public String getIdListByFullTextSearch(String pageId, String searchStr) {
        String url = String.format("%s/getIdsByStr?pageId=" + pageId + "&searchStr=" + searchStr, urlTemplate);
        String ids = restTemplate.getForEntity(url, String.class).getBody();
        return ids;
    }


    private void mergeClientQuery(QueryOption serverQuery, QueryParamDTO clientQuery) {
        if (clientQuery != null) {
            //替换query中的查询参数
            serverQuery.setPageIndex(clientQuery.getPageIndex());
            serverQuery.setPageSize(clientQuery.getPageSize());
            String clientSort = processClientSort(clientQuery.getSortField());
            //如果存在客户端排序条件，则客户端排序条件优先级高
            if (!StringUtils.isEmpty(clientSort)) {
                if (!StringUtils.isEmpty(serverQuery.getSortField())) {
                    serverQuery.setSortField(String.format("%s,%s", clientSort, serverQuery.getSortField()));
                } else {
                    serverQuery.setSortField(clientSort);
                }
            }
            serverQuery.setSortField(processSortField(serverQuery.getSortField()));
        }
    }


    private String processClientSort(String clientSortField) {
        if (StringUtils.isEmpty(clientSortField)) {
            return "";
        }
        String clientSort = "";
        //目前仅支持单列排序
        if (!clientSortField.contains(" ") || clientSortField.split(" ").length != 2 || clientSortField.contains(",")) {
            clientSort = "";
        } else {
            clientSort = clientSortField.toLowerCase().replace("#", ".");
        }
        return clientSort;
    }

    private String processSortField(String sortField) {
        //空或者只有1个排序字段则不处理
        if (StringUtils.isEmpty(sortField) || !sortField.contains(",")) {
            return sortField;
        }
        List<String> sortColumns = new ArrayList<>();
        List<String> allowSortField = new ArrayList<>();
        for (String sort : sortField.split(",")) {
            String columnCode = sort.split(" ")[0];
            if (!sortColumns.contains(columnCode)) {
                sortColumns.add(columnCode);
                allowSortField.add(sort);
            }
        }
        return String.join(",", allowSortField);
    }


    @Override
    public DbCollection getStatisticsInfo(String pageId, String searchParamsStr, String queryParamsStr, ClientMacro clientMacro, String rowValue, String colValue) {
        return getStatisticsInfo(pageId, searchParamsStr, queryParamsStr, clientMacro, rowValue, colValue, false);
    }

    @Override
    public DbCollection getStatisticsInfoNoPaging(String pageId, String searchParam, ClientMacro clientMacro, String rowValue, String colValue) {
        return getStatisticsInfo(pageId, searchParam, null, clientMacro, rowValue, colValue, true);
    }

    @SneakyThrows
    private DbCollection getStatisticsInfo(String pageId, String searchParamStr, String queryParamsStr, ClientMacro clientMacro, String rowValue, String colValue, Boolean allData) {
        if (StringUtils.isEmpty(pageId)) {
            return null;
        }
        SsPageEntity pageEntity = appFuncDataService.getPageById(pageId);
        //todo:此处需要验证是否有页面权限
        if (pageEntity == null || StringUtils.isEmpty(pageEntity.getGrid_query())) {
            return null;
        }
        QueryOption serverQuery = JSON.parseObject(pageEntity.getGrid_query(), QueryOption.class);
        //1、 附加搜索区域条件
        if (!StringUtils.isEmpty(searchParamStr)) {
            List<SearchCondition> list = JSON.parseArray(searchParamStr, SearchCondition.class);
            TableFilter searchFilter = searchCondition2TableFilterService.convertToTableFilter(list);
            if (searchFilter != null) {
                if (serverQuery.getTableFilter().getChildFilters() == null) {
                    serverQuery.getTableFilter().setChildFilters(new ArrayList<>());
                }
                serverQuery.getTableFilter().getChildFilters().add(searchFilter);
            }
        }
        //2、附件行列条件
        StatisticsOption statisticsOption = JSON.parseObject(pageEntity.getStatistics_setting(), StatisticsOption.class);
        mergeFilterQuery(serverQuery, statisticsOption, rowValue, colValue);
        //3、附件翻页信息
        if (!StringUtils.isEmpty(queryParamsStr)) {
            try {
                QueryParamDTO clientQuery = JSON.parseObject(queryParamsStr, QueryParamDTO.class);
                mergeClientQuery(serverQuery, clientQuery);
            } catch (Exception e) {
                throw new WarnCommonException(e.getMessage());
            }
        }

        if (StringUtils.isEmpty(serverQuery.getFixField())) {
            serverQuery.setFixField("*");
        }
        replaceClientMacro(serverQuery.getTableFilter(), clientMacro);
        serverQuery.setEnableColAccessControl(true);

        DbCollection coll = null;
        if (allData) {
            coll = dataAccess.queryAllData(serverQuery);
        } else {
            coll = dataAccess.query(serverQuery);
        }
        int i = 1;
        for (DbField f : coll.getTableInfo().getFieldList()) {
            f.setOrderId(i);
            i++;
        }
        return coll;
    }

    @SneakyThrows
    private void mergeFilterQuery(QueryOption serverQuery, StatisticsOption statisticsOption, String rowValue, String colValue) {

        TableFilterWrapper filterWrapper = TableFilterWrapper.and();
        DbTable table = dataAccess.initTableInfoByTableCode(serverQuery.getTableName());
        if (!StringUtils.isEmpty(rowValue)) {
            DbField rowField = table.getFieldList().stream().filter(f -> f.getCode().equals(statisticsOption.getRowField())).findFirst().orElse(null);
            if (rowField == null) {
                throw new WarnCommonException("统计行设置错误，表中不存在");
            }
            if (ServerMacroService.EMPTY_KEY.equals(rowValue)) {
                TableFilterWrapper wrapper = TableFilterWrapper.or();
                wrapper.eq(rowField.getCode(), rowValue);
                wrapper.isNull(rowField.getCode());
                filterWrapper.addFilter(wrapper.build());
            } else {
                filterWrapper.eq(rowField.getCode(), rowValue);
            }
        }
        if (!StringUtils.isEmpty(colValue)) {
            DbField columnField = table.getFieldList().stream().filter(f -> f.getCode().equals(statisticsOption.getColumnField())).findFirst().orElse(null);
            if (columnField == null) {
                throw new WarnCommonException("统计列设置错误，表中不存在");
            }
            if (ServerMacroService.EMPTY_KEY.equals(colValue)) {
                TableFilterWrapper wrapper = TableFilterWrapper.or();
                wrapper.eq(columnField.getCode(), colValue);
                wrapper.isNull(columnField.getCode());
                filterWrapper.addFilter(wrapper.build());
            } else {
                filterWrapper.eq(columnField.getCode(), colValue);
            }
        }
        if (serverQuery.getTableFilter().getChildFilters() == null) {
            serverQuery.getTableFilter().setChildFilters(new ArrayList<>());
        }
        serverQuery.getTableFilter().getChildFilters().add(filterWrapper.build());
    }


}
